package com.gufe.service.user.impl.Exhibition;

import com.gufe.dto.Exhibitions.ReservationDTO;
import com.gufe.entity.Exhibitions.Exhibition;
import com.gufe.entity.Exhibitions.Reservation;
import com.gufe.mapper.user.Exhibition.ExhibitionMapper;
import com.gufe.mapper.user.Exhibition.ReservationMapper;
import com.gufe.service.user.mp.Exhibition.ExhibitionService;
import com.gufe.vo.Exhibitions.ExhibitionVO;
import com.gufe.vo.Exhibitions.ReservationVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class ExhibitionServiceImpl implements ExhibitionService {

    @Autowired
    private ExhibitionMapper exhibitionMapper;

    @Autowired
    private ReservationMapper reservationMapper;

    @Override
    public List<ExhibitionVO> getAllExhibitions() {
        return exhibitionMapper.findAll().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Transactional
    @Override
    public void reserveExhibition(ReservationDTO reservationDTO) throws Exception {
        Optional<Exhibition> exhibitionOptional = exhibitionMapper.findById(reservationDTO.getExhibitionId());
        if (exhibitionOptional.isEmpty()) {
            throw new IllegalArgumentException("展览不存在");
        }
        Exhibition exhibition = exhibitionOptional.get();

        if (LocalDate.now().isBefore(exhibition.getStartDate()) || LocalDate.now().isAfter(exhibition.getEndDate())) {
            throw new IllegalStateException("该展览不在可预约时间内");
        }

        if (exhibition.getStatus()!=0) {
            throw new IllegalStateException("该展览当前不可预约");
        }

        if (exhibition.getReservedCount() >= exhibition.getCapacity()) {
            throw new IllegalStateException("该展览名额已满");
        }

        Optional<Reservation> existingReservation = reservationMapper.findByStudentId(reservationDTO.getStudentId());
        if (existingReservation.isPresent()) {
            throw new IllegalStateException("您已预约其他展览，无法再次预约");
        }

        Reservation reservation = new Reservation();
        BeanUtils.copyProperties(reservationDTO, reservation);
        reservation.setExhibitionId(exhibition.getId());
        reservationMapper.insert(reservation);

        exhibitionMapper.incrementReservedCount(exhibition.getId());
    }

    @Transactional
    @Override
    public void cancelReservation(ReservationDTO reservationDTO) throws Exception {
        Optional<Reservation> reservationOptional = reservationMapper.findByStudentIdAndExhibitionId(reservationDTO.getStudentId(), reservationDTO.getExhibitionId());
        if (reservationOptional.isEmpty()) {
            throw new IllegalArgumentException("未找到您的预约信息");
        }
        Reservation reservation = reservationOptional.get();

        Optional<Exhibition> exhibitionOptional = exhibitionMapper.findById(reservation.getExhibitionId());
        if (exhibitionOptional.isEmpty()) {
            throw new IllegalStateException("关联的展览不存在");
        }
        Exhibition exhibition = exhibitionOptional.get();

        if (reservation.isCanceled()) {
            throw new IllegalStateException("您已取消过本次预约，无法再次取消");
        }

        Reservation updateReservation = new Reservation();
        updateReservation.setId(reservation.getId());
        updateReservation.setCanceled(true);
        reservationMapper.updateCanceledStatus(updateReservation);

        if (exhibition.getReservedCount() > 0) {
            exhibitionMapper.decrementReservedCount(exhibition.getId());
        }
    }

    @Override
    public ReservationVO getReservationStatus(String studentId) {
        Optional<Reservation> reservationOptional = reservationMapper.findReservationWithExhibitionName(studentId);
        if (reservationOptional.isPresent()) {
            Reservation reservation = reservationOptional.get();
            ReservationVO reservationVO = new ReservationVO();
            BeanUtils.copyProperties(reservation, reservationVO);
            reservationVO.setExhibitionId(reservation.getExhibitionId()); // Manually set exhibitionId
            return reservationVO;
        }
        return null;
    }

    private ExhibitionVO convertToVO(Exhibition exhibition) {
        ExhibitionVO vo = new ExhibitionVO();
        BeanUtils.copyProperties(exhibition, vo);
        return vo;
    }
}